#include "Visual.h"
#include "Render/Animate/Animate.h"
#include "GameRender.h"
#include "Logic/State/State.h"
#include "Message/Message.h"


Visual::Visual(int type)
{
	m_elapsedTime = 0;
}

void Visual::AddAnimate(Animate* pAnimate)
{
	m_animateList.push_back(pAnimate);
}

void Visual::Render(int delta)
{
	if (m_renderMsgList.size() != 0)
	{
		RenderMessage* pMsg = m_renderMsgList.front();
		switch(pMsg->m_type)
		{
		case MSGTYPE_ENTITY_MOVE:
			DoRenderWalk(pMsg, delta);
			break;
		case MSGTYPE_ENTITY_STOP:
			DoRenderNone(pMsg, delta);
			break;
		case MSGTYPE_ENTITY_ATTACK:
			DoRenderAttack(pMsg, delta);
			break;
		case MSGTYPE_ENTITY_HURT:
			DoRenderHurt(pMsg, delta);
			break;
		default :
			assert(0);
		}
	}

	std::list<Animate*>::iterator itr = m_animateList.begin();
	while (itr != m_animateList.end())
	{
		(*itr)->Draw(delta);
		itr++;
	}
}

void Visual::DoRenderNone(RenderMessage* pMsg, int delta)
{
	m_renderData.state = FSM_STATE_NONE;

	SetRenderData(m_renderData);

	// remember to remove this render message when it's done.
	m_renderMsgList.pop_front();
	delete pMsg;
}


void Visual::DoRenderHurt(RenderMessage* pMsg, int delta)
{
	m_renderData.state = FSM_STATE_HURT;

	SetRenderData(m_renderData);

	// remember to remove this render message when it's done.
	m_renderMsgList.pop_front();
	delete pMsg;
}

void Visual::DoRenderAttack(RenderMessage* pMsg, int delta)
{
	m_elapsedTime += delta;
	m_renderData.time = pMsg->m_time;
	m_renderData.state = FSM_STATE_ATTACK;
	m_renderData.direction = pMsg->m_data3;

	if (m_elapsedTime < m_renderData.time)
	{
		//do nothing
	}
	else
	{
		m_renderMsgList.pop_front();
		delete pMsg;
		m_elapsedTime = 0;
	}

	SetRenderData(m_renderData);
}

void Visual::SetRenderData(const RenderData& data)
{
	m_renderData = data;
	std::list<Animate*>::iterator itr = m_animateList.begin();
	while (itr != m_animateList.end())
	{
		(*itr)->SetRenderData(data);
		itr++;
	}
}

void Visual::DoRenderWalk(RenderMessage* pMsg, int delta)
{
	m_elapsedTime += delta;
	m_renderData.time = pMsg->m_time;
	m_renderData.state = FSM_STATE_WALK;
	m_renderData.direction = pMsg->m_data3;
	POINT from, to;
	from.x = (pMsg->m_cell1.x()<<5) + 16;
	from.y = (pMsg->m_cell1.y()<<5) + 16;
	to.x   = (pMsg->m_cell2.x()<<5) + 16;
	to.y   = (pMsg->m_cell2.y()<<5) + 16;
	if (m_elapsedTime < m_renderData.time)
	{
		int dx = to.x - from.x;
		int dy = to.y - from.y;
		double scale = (double)m_elapsedTime / m_renderData.time;
		m_renderData.point.x = from.x + (int)(dx * scale);
		m_renderData.point.y = from.y + (int)(dy * scale);
	}
	else
	{
		m_renderData.point = to;
		m_renderMsgList.pop_front();
		delete pMsg;
		m_elapsedTime -= m_renderData.time;
	}

	SetRenderData(m_renderData);
}
void Visual::AddRenderMessage(RenderMessage *pMsg)
{
	m_renderMsgList.push_back(pMsg);
}